package x.mybatis.mapper;

import org.apache.ibatis.builder.annotation.ProviderContext;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSessionFactory;
import x.mybatis.lambda.Example;
import x.mybatis.metadata.TableMetadata;
import x.mybatis.metadata.TableMetadataHolder;
import x.mybatis.util.SpringContextUtils;

import java.lang.reflect.ParameterizedType;
import java.util.Collection;

/**
 * @author hanjuntao
 * @date 2025/5/9 0009
 */
public class BaseQueryMapperProvider extends BaseMapperProvider {
    /**
     * 测试使用xml
     *
     * @param example 查询出参数
     * @return
     */
    public String selectByExample(Object example, ProviderContext context) {
        SqlSessionFactory sessionFactory = SpringContextUtils.getBean(SqlSessionFactory.class);
        Configuration configuration = sessionFactory.getConfiguration();
        Collection<MappedStatement> mappedStatements =
                configuration.getMappedStatements();

        MappedStatement mappedStatement = mappedStatements.stream()
                .filter(item -> item.getId().equals(context.getMapperType().getName() + "." + context.getMapperMethod().getName()))
                .findFirst().orElse(null);
        if (mappedStatement == null) {
            throw new IllegalArgumentException("根据类：" +context.getMapperType().getName()
                    + ", 方法" + context.getMapperMethod().getName()+ "找不到对应的MappedStatement");
        }

        // 获取表名
        String tableName = getTableName(example, context);

        // 根据表达式，生成sql


        String sql = "SELECT id, name FROM " + tableName + " " + exampleWhereClause();

        return "<script>\n\t" + sql + "</script>";
    }

    public static String exampleWhereClause() {
        return "<if test=\"_parameter != null\">" +
                "<where>\n" +
                " ${@x.mybatis.util.OGNL@andNotLogicDelete(_parameter)}" +
                " <trim prefix=\"(\" prefixOverrides=\"and |or \" suffix=\")\">\n" +
                "  <foreach collection=\"oredCriteria\" item=\"criteria\">\n" +
                "    <if test=\"criteria.valid\">\n" +
                "      ${@x.mybatis.util.OGNL@andOr(criteria)}" +
                "      <trim prefix=\"(\" prefixOverrides=\"and |or \" suffix=\")\">\n" +
                "        <foreach collection=\"criteria.criteria\" item=\"criterion\">\n" +
                "          <choose>\n" +
                "            <when test=\"criterion.noValue\">\n" +
                "              ${@x.mybatis.util.OGNL@andOr(criterion)} ${criterion.condition}\n" +
                "            </when>\n" +
                "            <when test=\"criterion.singleValue\">\n" +
                "              ${@x.mybatis.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value}\n" +
                "            </when>\n" +
                "            <when test=\"criterion.betweenValue\">\n" +
                "              ${@x.mybatis.util.OGNL@andOr(criterion)} ${criterion.condition} #{criterion.value} and #{criterion.secondValue}\n" +
                "            </when>\n" +
                "            <when test=\"criterion.listValue\">\n" +
                "              ${@x.mybatis.util.OGNL@andOr(criterion)} ${criterion.condition}\n" +
                "              <foreach close=\")\" collection=\"criterion.value\" item=\"listItem\" open=\"(\" separator=\",\">\n" +
                "                #{listItem}\n" +
                "              </foreach>\n" +
                "            </when>\n" +
                "          </choose>\n" +
                "        </foreach>\n" +
                "      </trim>\n" +
                "    </if>\n" +
                "  </foreach>\n" +
                " </trim>\n" +
                "</where>" +
                "</if>";
    }

    private String getTableName(Object example, ProviderContext context) {
        Class<?> entityClass;
        if (example instanceof Example) {
            Example example1 = (Example) example;
            entityClass = example1.getEntityClass();
        } else {
            Class<?> mapperClass = context.getMapperType();
            // 获取泛型的类型
            entityClass = (Class<?>) ((ParameterizedType) mapperClass.getGenericInterfaces()[0]).getActualTypeArguments()[0];
        }

        TableMetadata tableMetadata = TableMetadataHolder.get(entityClass);

        return tableMetadata.getTableName();
    }

}
